package gatperdut.chato.core.interpreter.actions;

import gatperdut.chato.constants.CSConstantsCombat.AttackResult;
import gatperdut.chato.constants.CSConstantsCombat.BeAttackedResult;
import gatperdut.chato.constants.CSConstantsCommandResult.CommandExecutionResult;
import gatperdut.chato.core.characters.BaseController;
import gatperdut.chato.core.interpreter.actions.generic.Action;
import gatperdut.chato.core.interpreter.grammar.comminfo.HitInfo;

public class HitAction extends Action {

    public HitAction( HitInfo info, BaseController entityController ) {
        super( info, entityController );
    }

    @Override
    public CommandExecutionResult perform() {
        checkForRunningCraft();

        BaseController target = getEntityController().getRoomController().getCharactersController().getEntityController( getInfo().getWhom() );
        if ( target == null ) {
            getEntityController().tx( "You cannot find that character." );
            return CommandExecutionResult.OK;
        }

        if ( target == getEntityController() ) {
            getEntityController().tx( "You cannot attack yourself." );
            return CommandExecutionResult.OK;
        }

        if ( getEntityController().isPacifist() ) {
            getEntityController().tx( "Remove your pacifist flag first." );
            return CommandExecutionResult.OK;
        }

        AttackResult ar = getEntityController().getCombatController().attack( target );
        switch ( ar ) {
        case MUST_STOP_CRAFTING_FIRST:
            getEntityController().tx( "Stop crafting first." );
            return CommandExecutionResult.OK;
        case ATTACKING_SAME_TARGET:
            getEntityController().tx( "You are already doing your best against " + target.getCharacter().getShortDesc() + "!" );
            return CommandExecutionResult.OK;
        case RESUME_COMBAT:
            if ( getEntityController().getCombatController().getAttackers().contains( target ) ) {
                getEntityController().getEchoes().txStartFightingBack( target );
            }
            else {
                getEntityController().getEchoes().txStartCombat( target );
            }
            getEntityController().getCombatController().setTarget( target );
            handleNewTarget( target );
            break;
        case SHIFT_TO_DIFFERENT_TARGET:
            getEntityController().getEchoes().txShiftAttention( target );
            getEntityController().getCombatController().getTarget().getCombatController().removeAttacker( getEntityController() );
            BaseController oldTarget = getEntityController().getCombatController().getTarget();
            if ( oldTarget.getCombatController().combatCanEnd() ) {
                oldTarget.getCombatController().stopCombatThread();
            }
            getEntityController().getCombatController().setTarget( target );
            handleNewTarget( target );
            break;
        case STARTED_ATTACKING:
            getEntityController().getEchoes().txStartCombat( target );
            getEntityController().getCombatController().startCombatThread( target );
            handleNewTarget( target );
            break;
        case IS_SET_TO_PACIFIST:
            break;
        default:
            throw new IllegalArgumentException( "Unknown AttackResult." );
        }

        return CommandExecutionResult.OK;
    }

    private void handleNewTarget( BaseController target ) {
        BeAttackedResult bar = target.getCombatController().beAttacked( getEntityController() );
        switch ( bar ) {
        case ALREADY_FIGHTING:
            target.getCombatController().addAttacker( getEntityController() );
            target.getCombatController().handleBecomingNonPacifist( getEntityController() );
            break;
        case STARTED_ATTACKING:
            if ( target.isPacifist() ) {
                target.getCombatController().startCombatThread( null );
            }
            else {
                target.getCombatController().startCombatThread( getEntityController() );
                getEntityController().getCombatController().addAttacker( target );
            }
            target.getCombatController().addAttacker( getEntityController() );
            break;
        default:
            throw new IllegalArgumentException( "Unknown BeAttackedResult." );
        }
    }

    @Override
    public HitInfo getInfo() {
        return (HitInfo) super.getInfo();
    }

    @Override
    public boolean interruptsCrafting() {
        return false;
    }

}
